package com.mdx.rest.filter;

import com.mdx.rest.security.JWTProvider;
import com.mdx.rest.service.MyUserDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 添加Filter供spring-security解析token，并向securityContext中添加我们的用户信息。
 * 在UsernamePasswordAuthenticationFilter.class之前我们需要执行根据token添加authentication。关键方法是从jwt中获取authentication，然后添加到securityContext中。
 * 在SecurityConfiguration中需要设置Filter添加的位置
 *
 * @author : jiagang
 * @date : Created in 2022/2/10 10:43
 */
@Slf4j
@Component
public class JWTFilter extends OncePerRequestFilter {

    @Autowired
    private JWTProvider jwtProvider;

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;

    @Value("${jwt.tokenHead}")
    private String tokenHead;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            String authHeader = request.getHeader(tokenHeader);
            if (authHeader != null && authHeader.startsWith(tokenHead)){
                String authToken = authHeader.substring(tokenHead.length());
                String userName = jwtProvider.getUserNameFromToken(authToken);

                //token存在用户名但未登录
                if (null != userName && null == SecurityContextHolder.getContext().getAuthentication()) {
                    //登录
                    UserDetails userDetails = myUserDetailsService.loadUserByUsername(userName);
                    //验证token是否有效，重新设置用户对象
                    if (jwtProvider.validateToken(authToken, userDetails)) {
                        UsernamePasswordAuthenticationToken authenticationToken =
                                new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    }
                }
            }
            // 将请求转发给过滤器链上下一个对象 下一个filter
            filterChain.doFilter(request, response);

        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}
